package com.nnnu.wsnackshop.controller.user;

import com.nnnu.wsnackshop.constant.MessageConstants;
import com.nnnu.wsnackshop.exception.ObjectException;
import com.nnnu.wsnackshop.pojo.dto.ProductPageDTO;
import com.nnnu.wsnackshop.pojo.dto.ProductSearchDTO;
import com.nnnu.wsnackshop.pojo.vo.ProductVO;
import com.nnnu.wsnackshop.pojo.vo.SkuVO;
import com.nnnu.wsnackshop.result.PageResult;
import com.nnnu.wsnackshop.result.Result;
import com.nnnu.wsnackshop.service.IProductSkuService;
import com.nnnu.wsnackshop.service.IProductsService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;

/**
 * <p>
 * 用户端-商品 前端控制器
 * </p>
 *
 * @author zk
 * @since 2025-05-14
 */
@RestController("userProductsController")
@RequestMapping("/api/user/products")
@Tag(name = "用户端-商品接口")
@Slf4j
@Validated
@RequiredArgsConstructor
public class ProductsController {

    private final IProductsService productsService;
    private final IProductSkuService productSkuService;

    @Operation(summary = "分页查询商品", description = "分页查询已启用的商品，支持按分类、品牌、门店筛选，支持价格和销量排序")
    @GetMapping("/page")
    @Cacheable(cacheNames = "userProductPage", key = "'page:' + #dto.pageNum + ':size:' + #dto.pageSize + ':category:' + #dto.categoryId + ':store:' + #dto.storeId + ':spu:' + #dto.spuId + ':keyword:' + #dto.name + ':sortBy:' + #dto.sortBy + ':sortOrder:' + #dto.sortOrder + ':minPrice:' + #dto.minPrice + ':maxPrice:' + #dto.maxPrice", unless = "#result.data == null")
    public Result<PageResult<ProductVO>> pageProducts(@ParameterObject ProductPageDTO dto) {
        log.info("[用户端] 分页查询商品：{}", dto);
        // 强制只查询已启用的商品
        dto.setStatus(1);
        PageResult<ProductVO> result = productsService.pageProducts(dto);
        return Result.success(result, MessageConstants.SELECT_OK);
    }

    @Operation(summary = "获取商品详情", description = "获取已启用商品的详细信息")
    @GetMapping("/{id}")
    public Result<ProductVO> getProductDetail(@PathVariable("id") Integer id) {
        log.info("[用户端] 获取商品详情 id={}", id);
        ProductVO vo = productsService.getProductDetail(id);
        if (vo == null) {
            throw new ObjectException("商品不存在: " + id);
        }
        // 检查 status
        if (vo.getStatus() == null || vo.getStatus() != 1) {
            throw new ObjectException("商品未启用或不存在: " + id);
        }
        return Result.success(vo, MessageConstants.SELECT_OK);
    }

    @Operation(summary = "查询门店下某分类所有已启用商品", description = "返回指定门店下、指定分类下的启用商品列表")
    @GetMapping("/by-store/{storeId}/category/{categoryId}")
    @Cacheable(cacheNames = "userProductByStoreCategory", key = "'store:' + #storeId + ':category:' + #categoryId")
    public Result<List<ProductVO>> listProductsByStoreAndCategory(
            @PathVariable("storeId") Integer storeId,
            @PathVariable("categoryId") Integer categoryId) {
        log.info("[用户端] 查询门店下某分类商品, storeId={}, categoryId={}", storeId, categoryId);
        ProductPageDTO dto = new ProductPageDTO();
        dto.setPageNum(1);
        dto.setPageSize(1000); // 设置合理的上限
        dto.setStoreId(storeId);
        dto.setCategoryId(categoryId);
        dto.setStatus(1);
        PageResult<ProductVO> page = productsService.pageProducts(dto);
        return Result.success(page.getItems(), MessageConstants.SELECT_OK);
    }

    @Operation(summary = "查询门店下所有已启用商品", description = "返回指定门店下的所有启用商品")
    @GetMapping("/by-store/{storeId}")
    public Result<List<ProductVO>> listProductsByStore(@PathVariable("storeId") Integer storeId) {
        log.info("[用户端] 查询门店下所有商品, storeId={}", storeId);
        ProductPageDTO dto = new ProductPageDTO();
        dto.setPageNum(1);
        dto.setPageSize(1000);
        dto.setStoreId(storeId);
        dto.setStatus(1);
        PageResult<ProductVO> page = productsService.pageProducts(dto);
        return Result.success(page.getItems(), MessageConstants.SELECT_OK);
    }

    @Operation(summary = "查询分类下所有已启用商品", description = "返回指定分类下的所有启用商品，支持价格和销量排序")
    @GetMapping("/by-category/{categoryId}")
    @Cacheable(cacheNames = "userProductByCategory", key = "'category:' + #categoryId + ':sortBy:' + #sortBy + ':sortOrder:' + #sortOrder + ':page:' + #page + ':size:' + #pageSize", unless = "#result.data == null")
    public Result<List<ProductVO>> listProductsByCategory(
            @PathVariable("categoryId") Integer categoryId,
            @RequestParam(required = false) @Parameter(description = "排序字段") String sortBy,
            @RequestParam(required = false) @Parameter(description = "排序方式(asc/desc)") String sortOrder,
            @RequestParam(required = false, defaultValue = "1") @Parameter(description = "页码") Integer page,
            @RequestParam(required = false, defaultValue = "1000") @Parameter(description = "每页数量") Integer pageSize) {
        log.info("[用户端] 查询分类下所有商品, categoryId={}, sortBy={}, sortOrder={}, page={}, pageSize={}",
                categoryId, sortBy, sortOrder, page, pageSize);

        ProductPageDTO dto = new ProductPageDTO();
        dto.setPageNum(page);
        dto.setPageSize(pageSize);
        dto.setCategoryId(categoryId);
        dto.setStatus(1);
        dto.setSortBy(sortBy);
        dto.setSortOrder(sortOrder);

        // 使用新的查询方法
        PageResult<ProductVO> pageResult = productsService.pageProductsByCategory(dto);
        return Result.success(pageResult.getItems(), MessageConstants.SELECT_OK);
    }

    @Operation(summary = "搜索商品", description = "根据关键词搜索已启用的商品")
    @GetMapping("/search")
    public Result<PageResult<ProductVO>> searchProducts(ProductSearchDTO searchDTO) {
        log.info("[用户端] 搜索商品, searchDTO={}", searchDTO);
        return Result.success(productsService.searchProducts(searchDTO), MessageConstants.SELECT_OK);
    }

    @Operation(summary = "获取热门商品", description = "获取热门商品列表")
    @GetMapping("/popular")
    @Cacheable(cacheNames = "userProductPopular", key = "'popular:' + #limit + ':store:' + #storeId")
    public Result<List<ProductVO>> getPopularProducts(
            @RequestParam(defaultValue = "10") @Parameter(description = "返回数量") Integer limit,
            @RequestParam(required = false) @Parameter(description = "门店ID") Integer storeId) {
        log.info("[用户端] 获取热门商品, limit={}, storeId={}", limit, storeId);

        // 查询热门商品（按销量排序）
        ProductPageDTO dto = new ProductPageDTO();
        dto.setPageNum(1);
        dto.setPageSize(limit);
        dto.setStatus(1);
        dto.setStoreId(storeId);
        dto.setSortBy("sales");
        dto.setSortOrder("desc");

        PageResult<ProductVO> page = productsService.pageProducts(dto);
        return Result.success(page.getItems(), MessageConstants.SELECT_OK);
    }

    @Operation(summary = "获取新品推荐", description = "获取最新上架的商品列表")
    @GetMapping("/new")
    @Cacheable(cacheNames = "userProductNew", key = "'new:' + #limit + ':store:' + #storeId")
    public Result<List<ProductVO>> getNewProducts(
            @RequestParam(defaultValue = "10") @Parameter(description = "返回数量") Integer limit,
            @RequestParam(required = false) @Parameter(description = "门店ID") Integer storeId) {
        log.info("[用户端] 获取新品推荐, limit={}, storeId={}", limit, storeId);

        // 查询新品（按创建时间排序）
        ProductPageDTO dto = new ProductPageDTO();
        dto.setPageNum(1);
        dto.setPageSize(limit);
        dto.setStatus(1);
        dto.setStoreId(storeId);
        dto.setSortBy("create_time");
        dto.setSortOrder("desc");

        PageResult<ProductVO> page = productsService.pageProducts(dto);
        return Result.success(page.getItems(), MessageConstants.SELECT_OK);
    }

    @Operation(summary = "根据商品ID查询SKU列表", description = "返回指定商品ID下的所有SKU")
    @GetMapping("/{productId}/skus")
    public Result<List<SkuVO>> getProductSkus(@PathVariable("productId") Integer productId) {
        log.info("[用户端] 根据商品ID查询SKU列表, productId={}", productId);
        List<SkuVO> skus = productSkuService.listSkuByProduct(productId);
        return Result.success(skus, MessageConstants.SELECT_OK);
    }
}
